プログラミングやRPG(作るほう)が好きな人の日記
このホームページは毎日 夜11時にアクセスできなくなります。朝6時半に再開されます。
(世の中のネット依存対策として)
マイコンというのは、パソコンのCPUと同じようなもので、炊飯器や、高機能な湯沸かし器などいろいろな家電の中に入っていて、プログラムで家電を便利に操作してくれる電子回路部品です。電子工作では好きなプログラムをマイコンに書き込んで、創意工夫でいろいろなものを作ることができます。
秋月電子通商で販売されている、日立製作所のH8マイコン3052Fを載せたCPU(マイコン)ボードです。
ひさしぶりにはんだ付け作業を行いました。
左の画像リンクをクリックすると 画像を拡大 します。
上記のCPU(マイコン)ボードと液晶ディスプレイを、LAN機器の本体に装着して、電源を入れたところ。
LAN機器開発キットは、マイコンボード、液晶ディスプレイ、LAN機器本体の3点セットで8200円。
左の画像リンクをクリックすると 画像を拡大 します。
同じネットワーク上のパソコンからそのLAN機器のIPアドレスへ向けてPINGコマンドを打つと、このように返事が返ってきました。(私もPINGコマンドを使うのはあまり慣れているわけではありません)
左の画像リンクをクリックすると 画像を拡大 します。
どうしてLAN機器開発キットなのかというと、もうすぐ国家資格の「電子機器組立て1級」の資格取得の時期なんですが、ぜんぜんやる気がわいてこないんです。
そこで、自分への「てこ上げ」として、とりあえず何か電子工作をやってみようと思ったわけです。
で、私が失業してハローワークの電子回路エンジニア科を受講したときにもらった教科書(「C言語による組込み制御入門講座」という本があって、その本がまだ(長年)未着手だったので、これをやろうと思いました。
その本で取り扱っているマイコンが日立製作所H8マイコン3052Fだったというわけです。秋月電子通商で同マイコンを探したところ、手ごろだったのがLAN開発キットでした。
H8/3052Fはもうだいぶ古いマイコンと言われていますが、工業(産業)の世界では3052と同じシリーズで型番の少し違うものがまだ使われているって話を最近聞きました。枯れたシステム(完成されたシステム)では、わざわざ新しいものに変えることはなく、そのままの材料で作るのがベストだということでしょう。
古いマイコンとはいえ、マイコンとして完成されており、まだ使えるのに、古いというだけで「使えない」とされるのはもったいない気がします。でも新しいマイコンが次々と出てきて、古いマイコンの開発環境が更新されないまま古くさくなり、サポートも減って、その辺が「使えない」となってしまうんでしょう。
仕事でどことなく関係しているので、面白いと思っています(やる気が出始め)
上のメニューの aboutThisWebsite.html の「感想、意見 送信フォーム」でエラー表示(Internal Server Error)になっていましたが修正しました。
KONAMI のシューティングゲーム「グラディウスV」のスーパープレイのYouTube動画に衝撃を受けました。ゴージャスってこういうのを言うんだなと。
で、背景に動画(?)を使っているのを見て、動画(VIDEOタグ)と JavaScript の CANVAS を重ねられないかなと思ってやってみようと思いました。
それは結果としてできたんですが、それ以前に大事なことがあると思いました。
スーパープレイ動画の開始12秒から17秒までの5秒のあいだに、背景のアングルが大きく ぐるっ と変わるんですが、このカメラの魅力的な動き、普通はどうやるのか見当つかないと思うんです。
背景に動画を使うようなカラクリの話よりも、ダイナミックで魅力的な表現について説明するほうがニーズが高く、そこをほったらかしにするのは NG のような気がしました。
これから説明しますので、なるほどそういうことか、とわかってもらえれば幸いです。
動画と CANVAS を重ねる話はそのあとでしています。
(自機の当たり判定なし、無限ループ)
一般の こういうのをあまりやらない人にもわかるように説明したいと思います。
3DCGのレンダリングソフトの Shade3D を使いますが、「カメラワーク」の話なので、ほかのソフトでもやることは同じだと思います。
2020年11月14日追記:改めて自分でこの説明を読み直してみたところ、ちょっと Shade3D のしくみの話が多く、しかもわかりにくいと思いました。
ちなみに、Shade3Dは去年の暮れあたりから、通常の販売をすべてやめて、サブスクリプション(年ごとに支払いを繰り返す)になってしまい、ホビーユーザーは利用しづらくなりました。現在はパッケージの店頭売れ残りがあればラッキー(このリンクはAmazonで検索します)といった感じです。残念。
左の画像リンクをクリックすると 画像を拡大 します。
主に動画を説明材料にして説明していきます。
しかし、まず最初は動画ではなく、「カメラを動かさない状態」を見ていただくと、こんな感じです。
編集中: |
レンダリング結果:
|
上記 「編集中:」の画像の下のほうの線画の赤い物体が「カメラ」で、図の上のほうを向いている状態です。(下図に抜粋)
この状態からカメラワークのアニメを順番に加えていきます。
リング内を旋回するアニメを加えます。
カメラの位置だけを変更するアニメであり、首を振るアニメではないので、カメラは常に図の上を見ながら、リング内を回ります(下図赤矢印)。
編集中: |
レンダリング結果: |
リング内を回るのは、上図の「編集中:」の動画の右側のツリー表示で、「①パス(カメラ旋回移動用)」というフォルダの下に「カメラ」を入れているからそのように回ります。(下図に抜粋)
(※細かいアニメの設定はこのような画面で別途行います)
こういう単純な回転だけなら難しいことはないと思います。
今度はカメラはリングの中心を見ながら、リング内を回ります。
(このレンダリング結果ならゲームの背景にしても良さそうです)
編集中: |
レンダリング結果: |
上図の「編集中:」の動画の右側のツリー表示を見てもらうと、「①パス(…)」のフォルダの下にさらに「②回転(中心注視回転用)」というフォルダを作っているのがわかると思います。 (下図に抜粋)
これで、「カメラ」はリング内を旋回(いわゆる公転)しつつも、中心を見るように自転もしている、というアニメになります。
なお、下の自転だけにした動画を見てもらうと、「②回転(中心注視回転用)」によって自転だけしている というのがわかると思います。
リング内を旋回して、自転もする。
これもまぁ、ふつうの回転であって、難しいことはないと思います。
ではグラディウスVみたいに、背景のアングルが大きく ぐるっ と変わるのはどうやるんでしょうか。
リングの中心を見ていない、こういうアングルですね。
カメラがリングの左上くらい(下図)まで回ってきたところで、向いている方向をリングの中央ではなく、回ってきた道すじのほうを見るように(濃い青の矢印)アニメを追加します。
編集中: |
レンダリング結果: (目的達成) |
上図の「編集中:」の動画の右側のツリー表示を見てもらうと、フォルダ「①パス(…)」によるリング内旋回と、その下の「②回転(…)」で自転を行い、さらにその下に「③回転(左右首振り用)」というフォルダを作っていて、その下に「カメラ」があります。(下図に抜粋)
その「③回転(左右首振り用)」フォルダは「ある場所まで来たらちょっと首を後ろに振ってくれ」というような設定を別途行っています。正直ちょっとわかりづらい画面だと思うんですが下図のように設定しています。
ちょっと難しいですかね。これで上の「レンダリング結果:(目的達成)」のような動画になります。
つまり、今までの説明を要約すると「カメラの位置を変更(リング内を旋回)しつつ、ある時点でカメラの向いている向きをちょっと変えるんだ」ということです。一言で言うと「カメラの首を振れば良い」です。
わざわざここまで動画と画像を駆使して説明することもないんですが、私が一人で分かっていてこのページを見ている皆さんが「どうやるんだろう」と思いつつも分からないでいるというのは一番力を入れて解決すべきことだと思ったので頑張って説明しました。
つまり、単純に重ねればよいということです。
新しいウィンドウで実行 新しいウィンドウでMP4を表示(MP4: 1.57MB)
一連のファイルをまとめたZIP(1.94MB)です。おてもとで動かせます。「グラディウスV」でシューティングゲームの背景を動画(…ではなくリアルタイムのレンダリング?)にしてしまうなんてコナミの開発者の方はすごいことを考えたもんですね。
動画とゲームを融合させるというのはもとはスクエア・エニックスがファイナルファンタジー7で始めたことで(動画の最後の画面でそのままゲーム開始される)、パラサイトイヴ2では動画の再生中に動画の中のパースに合わせてキャラを操作することができたとか。
全体的に出来が良い気がします。
シリーズを面白い順に並べると、
1 → 6(今作) → 5(シンジケート) → 4(クレムリン爆破) → 3(ラビットフット) → 2(キメラ) です。
1作目が一番面白くて、2作目で大きく落として、シリーズを進めるごとに良くなってるみたいです。
でもそれでも今作も私が求めている1作目の痛快さがなく、普通のアクション映画っていう印象がぬぐえないかな。
良いところを言うと、雪山でヘリが転がるとき、転がってる最中のヘリの機内の はげしい様子がスゴくて、どうやって撮影しているんだろうと思いました。
iTunesサイト 「ミッション:インポッシブル フォールアウト」
プログラミングは何が楽しいかというと、「自分の思った通りに動いたとき何より楽しい!」とよく言われていると思います。
「こんなプログラムを作ろう」と思ってスタートし、プログラミングを行い、目的の結果が得られたらゴールです。
左図は、左下の青い S がプログラムのスタートで、右上の赤い G がプログラムのゴールです。S と G を結ぶ黄色い線がプログラムの出来栄えを表しており、S から G へ向かって直線であるほど、望ましいプログラムです。
目的のプログラムができたら(図で言うと G に到達したら)結構うれしくて、「やった!」と思います。
でも、目的のプログラムができたとしても、処理が遠回りだったり、処理が重かったりすると、一応できてはいるんだけど、もっといい方法があるんじゃないの?という出来栄えの場合もあります。
図で言うと、直線ではなく、湾曲しています。
それでもゴールに到達していれば、感動の宝物だったりするんですが。
または、志し半ばにして、目的の結果が得られず挫折する場合もあります。
図では、黄色い線が G に到達していません。
自分には出来ないんだ、なんて思って悲しくなることもあります。
ここで負けずに食い下がれるかどうかが、分かれ道かな?
しかしこういうものは あなた次第、だけではなく、これを読んでいる皆さんの周囲にいる 教える人の力量にもかかっています。
まぁ、最高のプログラムでなくても、ほどほどの出来栄えで目的の結果が得られれば、だいたい良いと思います。これがベストだと思います。
図で言うと、多少湾曲していても、まずまず、直線に近い感じです。
図は一本の線ですが、どんなプログラムにするかは人それぞれで、それがまた楽しいところでもあります。
いかにして より良いエレガントなプログラムにするか。
もっといい方法は…と四六時中考えて、仕事中にでも ふとしたことで「そうだ!その手があったか!」と思うと、そのあとは一日ウキウキとします。
プログラムがエレガントになる、というのは、ゴールに到達したときと同じような感動であり、プログラミングのもう1つの楽しみです。
「プログラミング 何が 楽しい」をキーワードにしてWEB検索してみると、「デバッグが難解パズルを解くみたいで楽しい」とか「他人のコードを見るとその人の思想を垣間見ることができて楽しい」とか「自分で書いたコードがどんどん動いていくのでだんだん楽しくなってきて…」とか「自分で作ったものが自分のiPhoneで動いて、作ったものが動いていることを実感できて楽しい」とか、人それぞれいろいろあるみたいです。
よりエレガントにするにはプログラムの手段をいろいろ知っている必要があると思います。なので、とてもやりがいのある分野じゃないかなと思います。
アニメーションプログラムの1つの形です。
ポーズからポーズへと遷移します。
左の画像リンクをクリックすると、新しいウィンドウを開いてJavaScriptを実行します。
赤、緑、青の3つのDIV要素が、4種類の配置(ポーズ)をつぎつぎと切り替えます。
ポーズとポーズのあいだは座標の増減で補間され、アニメーションになっています。
ポーズごとに時間の指定を変えているので、動きの速さに違いがあります。
<!DOCTYPE html><!--ESCAPEPROCESS-->
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>UntitledHomepage6047JavaScript</title>
<script>
console.clear();
console.log( "=============== script ==============" );
//単位を除去する。(Delete Unit)
function DU( value ) { return Number( value.replace( "px", "" ) ); }
function onloadx() {
timerMS = 50;
//各ポーズの作成
pose1 = new Pose( "pose1", 500 );
pose1.add( document.getElementById( "red" ).style, "left", 500 ),
pose1.add( document.getElementById( "green" ).style, "left", 500 ),
pose1.add( document.getElementById( "green" ).style, "top", 500 ),
pose1.add( document.getElementById( "blue" ).style, "top", 500 ),
/*
各ポーズのおおまかなデータ構造
pose1 ... new Pose
pose1.acts ... new Array
0 ... new Act HTML要素"red"のstyleのメンバ変数leftについて現在値から500まで値を変化させる
1 ... new Act 同様
2 ... new Act 同様
3 ... new Act 同様
pose2
:
:
*/
pose2 = new Pose( "pose2", 1300 );
pose2.add( document.getElementById( "red" ).style, "top", 500 ),
pose2.add( document.getElementById( "green" ).style, "top", 0 ),
pose2.add( document.getElementById( "blue" ).style, "left", 500 ),
pose3 = new Pose( "pose3", 500 );
pose3.add( document.getElementById( "red" ).style, "left", 0 ),
pose3.add( document.getElementById( "red" ).style, "top", 0 ),
pose3.add( document.getElementById( "green" ).style, "left", 0 ),
pose3.add( document.getElementById( "green" ).style, "top", 500 ),
pose3.add( document.getElementById( "blue" ).style, "top", 0 ),
pose4 = new Pose( "pose4", 1300 );
pose4.add( document.getElementById( "red" ).style, "left", 0 ),
pose4.add( document.getElementById( "red" ).style, "top", 0 ),
pose4.add( document.getElementById( "green" ).style, "left", 0 ),
pose4.add( document.getElementById( "green" ).style, "top", 0 ),
pose4.add( document.getElementById( "blue" ).style, "left", 0 ),
pose4.add( document.getElementById( "blue" ).style, "top", 0 ),
//シーケンス作成 (あるポーズを取ったら、次のポーズへ向かって値を遷移させる)
pose1.nextPose = pose2;
pose2.nextPose = pose3;
pose3.nextPose = pose4;
pose4.nextPose = pose1;
currentPose = pose1;
currentPose.ready();
timerID = setInterval( frame, timerMS );
}
//1フレーム分の動作
function frame() {
currentPose.frame();
//check. ポーズが完了したら次のポーズへ
if( currentPose.endFlg ) {
currentPose = currentPose.nextPose;
currentPose.ready();
}
}
//クラス1: 1つのポーズを形作る、Actの集合
function Pose( title, time ) {
/*
time この時間内にアニメーションを終わらせる
*/
this.title = title;
this.time = time;
this.acts = new Array();
this.endFlg = false;
}
//actsにActを追加する
Pose.prototype.add = function( object, objectMember, endValue ) {
this.acts.push( new Act( object, objectMember, endValue, this.time ) );
}
//1フレーム分の動作
Pose.prototype.frame = function() {
//すべてのActが終了したら、このポーズは完了
var allEnd = true;
for( var i = 0; i < this.acts.length; i++ ) {
var act = this.acts[ i ];
if( ! act.endFlg ) {
allEnd = false;
break;
}
}
if( allEnd ){
this.endFlg = true;
return;
}
//Actを進行
for( var i = 0; i < this.acts.length; i++ ) {
this.acts[ i ].frame();
}
}
//現在の状況(DOMの現在値)に合わせて、初期化
Pose.prototype.ready = function() {
console.log( this.title + " へ" );
for( var i = 0; i < this.acts.length; i++ ) {
this.acts[ i ].ready();
}
this.endFlg = false;
}
//クラス2: オブジェクトのあるメンバ変数を、現在値からendValueまで、time時間かけて遷移させる
function Act( object, objectMember, endValue, time ) {
this.object = object;
this.objectMember = objectMember;
this.endValue = endValue;
this.time = time;
this.direction = 0;
this.step = 0;
this.endFlg = false;
}
//現在の状況に合わせて、初期化
Act.prototype.ready = function() {
//現在値から目標値までの距離
var len = this.endValue - DU( this.object[ this.objectMember ] );
//check.すでに到達
if( len == 0 ) {
this.endFlg = true;
return;
}
this.direction = len > 0 ? 1 : -1;
this.step = len / ( this.time / timerMS );
this.endFlg = false;
}
//1フレーム分の動作
Act.prototype.frame = function() {
this.increment();
}
//進行
Act.prototype.increment = function() {
if( this.object[ this.objectMember ].match( /px/ ) )
this.object[ this.objectMember ] = ( DU( this.object[ this.objectMember ] ) + this.step ) + "px";
else
this.object[ this.objectMember ] += this.step;
this.endFlg = DU( this.object[ this.objectMember ] ) * this.direction >= this.endValue * this.direction;
//check.終了の場合は、余分な移動を補正する
if( this.endFlg ) {
if( this.object[ this.objectMember ].match( /px/ ) )
this.object[ this.objectMember ] = this.endValue + "px";
else
this.object[ this.objectMember ] = this.endValue;
}
}
</script>
<style>
</style>
</head>
<body onload="onloadx();" style="background-color:white;">
<div id="red" style="
position : absolute;
background-color : red;
left : 0px;
top : 0px;
width : 32px;
height : 32px;
opacity : .5;
"></div>
<div id="green" style="
position : absolute;
background-color : green;
left : 0px;
top : 0px;
width : 32px;
height : 32px;
opacity : .5;
"></div>
<div id="blue" style="
position : absolute;
background-color : blue;
left : 0px;
top : 0px;
width : 32px;
height : 32px;
opacity : .5;
"></div>
</body>
</html>
(このプログラムは著作権を特に主張しませんので気に入ったら自由にコピペして使ってください)
(2007年アメリカ/サスペンス/1:36/一般評価★★★☆☆/私評価★★★★★)
人間ドラマとしてしっかりしているし、SF(起こりそうも無い事を起こりそうに描いたもの)としても楽しめると思います。人間ドラマを見て泣いたことがある人は、この映画はおススメです。埋もれた名作だと思ったんだけど、私が一人でそう思っているだけなのかな。